home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / programming / assembly / consoledevice.lha / console.c next >
Encoding:
C/C++ Source or Header  |  1993-08-31  |  12.9 KB  |  375 lines

  1. ;/* console.c - Execute me to compile me with Lattice 5.04
  2. LC -b1 -cfistq -v -y -j73 console.c
  3. Blink FROM LIB:c.o,console.o TO console LIBRARY LIB:LC.lib,LIB:Amiga.lib
  4. quit
  5. */
  6.  
  7. /* Console.c - console.device example
  8.  *
  9.  * Copyright (c) 1990 Commodore-Amiga, Inc.
  10.  *
  11.  * This example is provided in electronic form by Commodore-Amiga, Inc. for
  12.  * use with the 1.3 revisions of the Addison-Wesley Amiga reference manuals. 
  13.  * The 1.3 Addison-Wesley Amiga Reference Manual series contains additional
  14.  * information on the correct usage of the techniques and operating system
  15.  * functions presented in this example.  The source and executable code of
  16.  * this example may only be distributed in free electronic form, via bulletin
  17.  * board or as part of a fully non-commercial and freely redistributable
  18.  * diskette.  Both the source and executable code (including comments) must
  19.  * be included, without modification, in any copy.  This example may not be
  20.  * published in printed form or distributed with any commercial product.
  21.  * However, the programming techniques and support routines set forth in
  22.  * this example may be used in the development of original executable
  23.  * software products for Commodore Amiga computers.
  24.  * All other rights reserved.
  25.  * This example is provided "as-is" and is subject to change; no warranties
  26.  * are made.  All use is at your own risk.  No liability or responsibility
  27.  * is assumed.
  28.  */
  29.  
  30. #include <exec/types.h>
  31. #include <exec/io.h>
  32. #include <exec/memory.h>
  33. #include <intuition/intuition.h>
  34. #include <libraries/dos.h>
  35. #include <devices/console.h>
  36. #ifdef LATTICE
  37. #include <proto/all.h>
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <string.h>
  41. int CXBRK(void) { return(0); }        /* Disable Lattice CTRL/C handling */
  42. int chkabort(void) { return(0); }    /* really */
  43. #endif
  44.  
  45. /* Note - using two character <CSI> ESC[.  Hex 9B could be used instead */ 
  46. #define RESETCON  "\033c"
  47. #define CURSOFF   "\033[0 p"
  48. #define CURSON    "\033[ p"
  49. #define DELCHAR   "\033[P"
  50.  
  51. /* SGR (set graphic rendition) */
  52. #define COLOR02   "\033[32m"
  53. #define COLOR03   "\033[33m"
  54. #define ITALICS   "\033[3m"
  55. #define BOLD      "\033[1m"
  56. #define UNDERLINE "\033[4m"
  57. #define NORMAL    "\033[0m"
  58.  
  59. /* our functions */
  60. void cleanexit(UBYTE *,LONG);
  61. void cleanup(void);
  62. BYTE OpenConsole(struct IOStdReq *,struct IOStdReq *, struct Window *);
  63. void CloseConsole(struct IOStdReq *);
  64. void QueueRead(struct IOStdReq *, UBYTE *);
  65. UBYTE ConGetChar(struct MsgPort *, UBYTE *);
  66. LONG ConMayGetChar(struct MsgPort *, UBYTE *);
  67. void ConPuts(struct IOStdReq *, UBYTE *);
  68. void ConWrite(struct IOStdReq *, UBYTE *, LONG);
  69. void ConPutChar(struct IOStdReq *, UBYTE);
  70.  
  71. struct NewWindow nw = {
  72.         10, 10,                           /* starting position (left,top) */
  73.         620,180,                          /* width, height */
  74.         -1,-1,                            /* detailpen, blockpen */
  75.         CLOSEWINDOW,                      /* flags for idcmp */
  76.         WINDOWDEPTH|WINDOWSIZING|
  77.         WINDOWDRAG|WINDOWCLOSE|
  78.         SMART_REFRESH|ACTIVATE,           /* window flags */
  79.         NULL,                             /* no user gadgets */
  80.         NULL,                             /* no user checkmark */
  81.         "Console Test",                   /* title */
  82.         NULL,                             /* pointer to window screen */
  83.         NULL,                             /* pointer to super bitmap */
  84.         100,45,                           /* min width, height */
  85.         640,200,                          /* max width, height */
  86.         WBENCHSCREEN                      /* open on workbench screen */
  87.         };
  88.  
  89.  
  90. /* Opens/allocations we'll need to clean up */
  91. struct Library  *IntuitionBase = NULL;
  92. struct Window   *win = NULL;
  93. struct IOStdReq *writeReq = NULL;    /* I/O request block pointer */
  94. struct MsgPort  *writePort = NULL;   /* replyport for writes      */   
  95. struct IOStdReq *readReq = NULL;     /* I/O request block pointer */
  96. struct MsgPort  *readPort = NULL;    /* replyport for reads       */   
  97. BOOL OpenedConsole = FALSE;
  98.  
  99. BOOL FromWb;
  100.  
  101. void main(int argc, char **argv)
  102.     {
  103.     struct IntuiMessage *winmsg;
  104.     ULONG signals, conreadsig, windowsig;
  105.     LONG lch;
  106.     SHORT InControl = 0;
  107.     BOOL Done = FALSE;
  108.     UBYTE ch, ibuf;
  109.     UBYTE obuf[200];
  110.     BYTE error;
  111.  
  112.     FromWb = (argc==0L) ? TRUE : FALSE;
  113.  
  114.     if(!(IntuitionBase=OpenLibrary("intuition.library",0)))
  115.          cleanexit("Can't open intuition\n",RETURN_FAIL);
  116.  
  117.     /* Create reply port and io block for writing to console */
  118.     if(!(writePort = CreatePort("RKM.console.write",0)))
  119.          cleanexit("Can't create write port\n",RETURN_FAIL);
  120.  
  121.     if(!(writeReq = (struct IOStdReq *)
  122.     CreateExtIO(writePort,(LONG)sizeof(struct IOStdReq))))
  123.          cleanexit("Can't create write request\n",RETURN_FAIL);
  124.  
  125.     /* Create reply port and io block for reading from console */
  126.     if(!(readPort = CreatePort("RKM.console.read",0)))
  127.          cleanexit("Can't create read port\n",RETURN_FAIL);
  128.  
  129.     if(!(readReq = (struct IOStdReq *)
  130.     CreateExtIO(readPort,(LONG)sizeof(struct IOStdReq))))
  131.          cleanexit("Can't create read request\n",RETURN_FAIL);
  132.  
  133.     /* Open a window */
  134.     if(!(win = OpenWindow(&nw)))
  135.          cleanexit("Can't open window\n",RETURN_FAIL);
  136.  
  137.     /* Now, attach a console to the window */
  138.     if(error = OpenConsole(writeReq,readReq,win))
  139.          cleanexit("Can't open console.device\n",RETURN_FAIL);
  140.     else OpenedConsole = TRUE;
  141.  
  142.     /* Demonstrate some console escape sequences */
  143.     ConPuts(writeReq,"Here's some normal text\n");
  144.     sprintf(obuf,"%s%sHere's text in color 3 and italics\n",COLOR03,ITALICS);
  145.     ConPuts(writeReq,obuf);
  146.     ConPuts(writeReq,NORMAL);
  147.     Delay(50);      /* Delay for dramatic demo effect */
  148.     ConPuts(writeReq,"We will now delete this asterisk =*=");
  149.     Delay(50); 
  150.     ConPuts(writeReq,"\b\b");  /* backspace twice */
  151.     Delay(50);
  152.     ConPuts(writeReq,DELCHAR); /* delete the character */
  153.     Delay(50);
  154.  
  155.     QueueRead(readReq,&ibuf); /* send the first console read request */
  156.  
  157.     ConPuts(writeReq,"\n\nNow reading console\n");
  158.     ConPuts(writeReq,"Type some keys.  Close window when done.\n\n");
  159.  
  160.     conreadsig = 1 << readPort->mp_SigBit;
  161.     windowsig = 1 << win->UserPort->mp_SigBit;
  162.  
  163.     while(!Done)
  164.         {
  165.         /* A character, or an IDCMP msg, or both could wake us up */
  166.         signals = Wait(conreadsig|windowsig);
  167.  
  168.         /* If a console signal was received, get the character */
  169.         if (signals & conreadsig)
  170.             {        
  171.             if((lch = ConMayGetChar(readPort,&ibuf)) != -1)
  172.                 {
  173.                 ch = lch;
  174.                 /* Show hex and ascii (if printable) for char we got.
  175.                  * If you want to parse received control sequences, such as
  176.                  * function or Help keys, you would buffer control sequences
  177.                  * as you receive them, starting to buffer whenever you
  178.                  * receive 0x9B (or 0x1B[ for user-typed sequences) and
  179.                  * ending when you receive a valid terminating character
  180.                  * for the type of control sequence you are receiving.
  181.                  * For CSI sequences, valid terminating characters
  182.                  * are generally 0x40 through 0x7E.
  183.                  * In our example, InControl has the following values:
  184.                  * 0 = no, 1 = have 0x1B, 2 = have 0x9B OR 0x1B and [,
  185.                  * 3 = now inside control sequence, -1 = normal end esc,
  186.                  * -2 = non-CSI(no [) 0x1B end esc
  187.                  * NOTE - a more complex parser is required to recognize
  188.                  *  other types of control sequences.
  189.                  */ 
  190.  
  191.                 /* 0x1B ESC not followed by '[', is not CSI seq */
  192.                 if (InControl==1)
  193.                     {
  194.                     if(ch=='[') InControl = 2;
  195.                     else InControl = -2;
  196.                     }
  197.  
  198.                 if ((ch==0x9B)||(ch==0x1B))  /* Control seq starting */
  199.                     {
  200.                     InControl = (ch==0x1B) ? 1 : 2;
  201.                     ConPuts(writeReq,"=== Control Seq ===\n");
  202.                     }
  203.  
  204.                 /* We'll show value of this char we received */
  205.                 if (((ch >= 0x1F)&&(ch <= 0x7E))||(ch >= 0xA0))
  206.                    sprintf(obuf,"Received: hex %02x = %c\n",ch,ch);
  207.                 else sprintf(obuf,"Received: hex %02x\n",ch);
  208.                 ConPuts(writeReq,obuf);
  209.  
  210.                 /* Valid ESC sequence terminator ends an ESC seq */
  211.                 if ((InControl==3)&&((ch >= 0x40) && (ch <= 0x7E)))
  212.                     {
  213.                     InControl = -1;
  214.                     }
  215.                 if (InControl==2) InControl = 3;
  216.                 /* ESC sequence finished (-1 if OK, -2 if bogus) */
  217.                 if (InControl < 0) 
  218.                     {
  219.                     InControl = 0;
  220.                     ConPuts(writeReq,"=== End Control ===\n");
  221.                     }
  222.                 }
  223.             }
  224.  
  225.         /* If IDCMP messages received, handle them */
  226.         if (signals & windowsig)
  227.             {
  228.             /* We have to ReplyMsg these when done with them */
  229.             while (winmsg = (struct IntuiMessage *)GetMsg(win->UserPort))
  230.                 {
  231.                 switch(winmsg->Class)
  232.                     {
  233.                     case CLOSEWINDOW:
  234.                       Done = TRUE;
  235.                       break;
  236.                     default:
  237.                       break;
  238.                      }
  239.                 ReplyMsg((struct Message *)winmsg);
  240.                 }
  241.             }
  242.         }
  243.  
  244.     /* We always have an outstanding queued read request
  245.      * so we must abort it if it hasn't completed,
  246.      * and we must remove it.
  247.      */
  248.     if(!(CheckIO(readReq)))  AbortIO(readReq);
  249.     WaitIO(readReq);     /* clear it from our replyport */
  250.  
  251.     cleanup();
  252.     exit(RETURN_OK);
  253.     }
  254.  
  255. void cleanexit(UBYTE *s,LONG n)
  256.     {
  257.     if(*s & (!FromWb)) printf(s);
  258.     cleanup();
  259.     exit(n);
  260.     }
  261.  
  262. void cleanup()
  263.     {
  264.     if(OpenedConsole) CloseConsole(writeReq);
  265.     if(readReq)       DeleteExtIO(readReq);
  266.     if(readPort)      DeletePort(readPort);
  267.     if(writeReq)      DeleteExtIO(writeReq);
  268.     if(writePort)     DeletePort(writePort);
  269.     if(win)           CloseWindow(win);
  270.     if(IntuitionBase) CloseLibrary(IntuitionBase);
  271.     }
  272.  
  273.  
  274. /* Attach console device to an open Intuition window.
  275.  * This function returns a value of 0 if the console 
  276.  * device opened correctly and a nonzero value (the error
  277.  * returned from OpenDevice) if there was an error.
  278.  */
  279. BYTE OpenConsole(writereq, readreq, window)
  280. struct IOStdReq *writereq;
  281. struct IOStdReq *readreq;
  282. struct Window *window;
  283.     {
  284.     BYTE error;
  285.    
  286.     writereq->io_Data = (APTR) window;
  287.     writereq->io_Length = sizeof(struct Window);
  288.     error = OpenDevice("console.device", 0, writereq, 0);
  289.     readreq->io_Device = writereq->io_Device; /* clone required parts */
  290.     readreq->io_Unit   = writereq->io_Unit;
  291.     return(error);   
  292.     }
  293.  
  294. void CloseConsole(struct IOStdReq *writereq)
  295.     {
  296.     CloseDevice(writereq);
  297.     }
  298.  
  299. /* Output a single character to a specified console 
  300.  */ 
  301. void ConPutChar(struct IOStdReq *writereq, UBYTE character)
  302.     {
  303.     writereq->io_Command = CMD_WRITE;
  304.     writereq->io_Data = (APTR)&character;
  305.     writereq->io_Length = 1;
  306.     DoIO(writereq);
  307.     /* command works because DoIO blocks until command is done
  308.      * (otherwise ptr to the character could become invalid)
  309.      */
  310.     }
  311.  
  312.  
  313. /* Output a stream of known length to a console 
  314.  */ 
  315. void ConWrite(struct IOStdReq *writereq, UBYTE *string, LONG length)
  316.     {
  317.     writereq->io_Command = CMD_WRITE;
  318.     writereq->io_Data = (APTR)string;
  319.     writereq->io_Length = length; 
  320.     DoIO(writereq);
  321.     /* command works because DoIO blocks until command is done
  322.      * (otherwise ptr to string could become invalid in the meantime)
  323.      */
  324.    }
  325.  
  326.  
  327. /* Output a NULL-terminated string of characters to a console 
  328.  */ 
  329. void ConPuts(struct IOStdReq *writereq,UBYTE *string)
  330.     {
  331.     writereq->io_Command = CMD_WRITE;
  332.     writereq->io_Data = (APTR)string;
  333.     writereq->io_Length = -1;  /* means print till terminating null */
  334.     DoIO(writereq);
  335.     }
  336.  
  337. /* Queue up a read request to console, passing it pointer
  338.  * to a buffer into which it can read the character
  339.  */
  340. void QueueRead(struct IOStdReq *readreq, UBYTE *whereto)
  341.    {
  342.    readreq->io_Command = CMD_READ;
  343.    readreq->io_Data = (APTR)whereto;
  344.    readreq->io_Length = 1;
  345.    SendIO(readreq);
  346.    }
  347.  
  348. /* Check if a character has been received.
  349.  * If none, return -1 
  350.  */
  351. LONG ConMayGetChar(struct MsgPort *msgport, UBYTE *whereto)
  352.     {
  353.     register temp;
  354.     struct IOStdReq *readreq;
  355.  
  356.     if (!(readreq = (struct IOStdReq *)GetMsg(msgport))) return(-1);
  357.     temp = *whereto;                /* get the character */
  358.     QueueRead(readreq,whereto);     /* then re-use the request block */
  359.     return(temp);
  360.     }
  361.  
  362. /* Wait for a character
  363.  */
  364. UBYTE ConGetChar(struct MsgPort *msgport, UBYTE *whereto)
  365.     {
  366.     register temp;
  367.     struct IOStdReq *readreq;
  368.  
  369.     WaitPort(msgport);
  370.     readreq = (struct IOStdReq *)GetMsg(msgport);
  371.     temp = *whereto;               /* get the character */
  372.     QueueRead(readreq,whereto);    /* then re-use the request block*/
  373.     return((UBYTE)temp);
  374.     }
  375.